package com.cda.service.impl;

import com.cda.common.BaseLogger;
import com.cda.common.CommandPos2;
import com.cda.dao.MonneyInfoLogDao;
import com.cda.dao.SfGatelogEntityDao;
import com.cda.entity.MonneyInfoLog;
import com.cda.entity.Person;
import com.cda.entity.SfGatelogEntity;
import com.cda.entity.SfdevicebindEntity;
import com.cda.service.FaceService;
import com.cda.service.PosInputInfoSevice;
import com.cda.service.SfdevicebindService;
import com.cda.utils.FaceHttpClientUtil;
import com.cda.utils.StringUtils;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import net.sf.json.JSONObject;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

/**
 * Created by peiming on 2019/3/6.
 */
@Service("posInputInfoService")
public class PosInputInfoServiceImpl extends BaseLogger implements PosInputInfoSevice {

   public  static Map<String,String> baseMap=new HashMap<>();

    @Autowired
    private MonneyInfoLogDao monneyInfoLogDao;
    @Autowired
    private SfGatelogEntityDao sfGatelogEntityDao;

    @Autowired
    FaceService faceService;

    @Autowired
    private SfdevicebindService sfdevicebindService;
    @Value("${pos.log.url}")
    private String dataFileUrl;
    @Value("${device.open.vol}")
    private String vol;
    @Value("${device.open.screemconten}")
    private String screemconten;
    @Value("${face.name}")
    private String faceName;
    @Value("${open.door.url}")
    private String openDoorUrl;
    @Value("${face.repeat.count}")
    int repeatCount;



     static List<MonneyInfoLog> monneyInfoLogList=new ArrayList<MonneyInfoLog>();
    @Override
   // @Scheduled(cron="${pos.time.value}")
    public void excuteByTime() throws Exception{
        //先判断是否在消费时间
        String inputStr="D2015 A001 030000000000000000111900000000016700000000009800000000000272030 5000000000015 333333333333333333333333333333333333333333333333333333333333333 33333333333333333333333333333333333333333 W20150616205755001 ";
        if(isWork()){

        //查询交易金额
        SfdevicebindEntity sfdevicebindEntity =sfdevicebindService.findByClientIp(getHostIp());
        //根据长度补足字节数
        if( sfdevicebindEntity == null ){
            logger.info("设备绑定表数据为null，请配置");
        }
        String aStri="";
        for(int i=0;i<(12-sfdevicebindEntity.getPosSum().length());i++){
            aStri+="0";
        }
        CommandPos2.CLibrary.InputData.ByReference inputData = new CommandPos2.CLibrary.InputData.ByReference();
         inputData.amount=Arrays.copyOf((aStri+sfdevicebindEntity.getPosSum()).getBytes(), 12);  ;//设置交易金额ng
        inputData.trans=Arrays.copyOf("00".getBytes(), 2);
        Pointer result =new Memory(1024);
            inputData.write();
        int flag= CommandPos2.CLibrary.INSTANCE.BankTrans(inputData,result);
        String outStr=new String(result.getByteArray(0,1024),"GBK");
        //System.out.println("outPutData:"+new String(result.getByteArray(0,1024),"GBK"));
        System.gc();
        long peer1=Pointer.nativeValue(result);
        Native.free(peer1);
        Pointer.nativeValue(result, 0);
        //"T5                                                                                2019                                         与密码键盘通讯失败                                                                                  00     t e s t \ l o g . i n i                                                      ";
        //outStr="0001026212263602090193574           26110000000000010000439081021109620123450000012019032302540910500008999914010064157        交易成功                                          42BA2F76D9B12CD7CC39C5D1689CBD4E                  00                                                                                                                                                                                                                                                                                                                                                                                                                                                   d  d漙   o\\ X$] 8 6 ) \\ I n t e l \\ O p e n C L   S D K \\ 2 . 0 \\ b i n \\ x 6 4 ; C : \\ P r o g r a m   F i l e s \\ I n t e l \\ I n t e l ( R )   M a n a g e m e n t   E n g i n e   C o m p o n e n t s \\ D A L ; C : \\ P r o g r a m   F i l e s \\ I n t e l \\ I n t e l ( R )   M a n a g e m e n t   E n g i n e   C o m p o n e n t s \\ I P T ; C : \\ P r o g r a ";

        if(flag==0){
            logger.info("发送指令到pos机成功");
        //得到响应数据开始解析
            MonneyInfoLog monneyInfoLog=new MonneyInfoLog();
        if(StringUtils.isNotEmpty(outStr)){
            //获取返回码
            String respCode=outStr.substring(0,2).trim();
            String resp_chin=outStr.substring(127,173);
            monneyInfoLog.setRespCode(respCode);
            monneyInfoLog.setRespChin(resp_chin.trim());
            //交易成功爆出数据开闸门
            if("00".equals(respCode)){
                String bank_code=outStr.substring(2,6);
                String card_no=outStr.substring(6,36);
                String expr=outStr.substring(36,40);
                String  amount=outStr.substring(40,52);
                String  trace=outStr.substring(52,58);
                String  refer=outStr.substring(58,70);
                String  auth=outStr.substring(70,76);
                String  batch=outStr.substring(76,82);
                String  date=outStr.substring(82,96);
                String  userno=outStr.substring(96,111);
                String  terno=outStr.substring(111,119);
                String old_terno=outStr.substring(119,127);
                String  OrderNo=outStr.substring(173,222);
                String  lrc=outStr.substring(222,225);
                monneyInfoLog.setBankCode(bank_code);
                monneyInfoLog.setCardNo(card_no);
                monneyInfoLog.setExprDate(expr);
                monneyInfoLog.setAmount(Integer.parseInt(amount) + "");
                monneyInfoLog.setTraceNo(trace);
                monneyInfoLog.setRefer(refer);
                monneyInfoLog.setAuthNo(auth);
                monneyInfoLog.setBatchNo(batch);
                monneyInfoLog.setPayDate(org.apache.commons.lang3.time.DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyymmdHHhmmss"), "yyyymmdHHhmmss"));
                monneyInfoLog.setUserno(userno);
                monneyInfoLog.setTerno(terno);
                monneyInfoLog.setOldTerno(old_terno);
                monneyInfoLog.setOrderno(OrderNo);
                monneyInfoLog.setLrc(lrc);
                monneyInfoLog.setCreateDate(new Date());
                SfdevicebindEntity sfdevicebindEntity1 =sfdevicebindService.findByClientIp(getHostIp());
                monneyInfoLog.setDeviceNo(sfdevicebindEntity1.getName());
                //保持交易日志
                try {
                    monneyInfoLog.setId(UUID.randomUUID().toString());
                    monneyInfoLogDao.save(monneyInfoLog);
                }catch (Exception e){
                    try {
                        //保存数据失败将数据放到本地
                        //每一次都会清空原来的数据
                        monneyInfoLogList.add(monneyInfoLog);
                        FileOutputStream fos=new FileOutputStream(dataFileUrl);
                        ObjectOutputStream oos = new ObjectOutputStream(fos);
                        oos.writeObject(monneyInfoLogList);
                        System.out.println(monneyInfoLogList);
                        oos.close();
                    }catch (Exception xe){
                        logger.error("保存数据到本地异常");
                        xe.printStackTrace();
                    }
                }
                boolean flag2  = control(monneyInfoLog);//开闸

            }


            }
        }
        }
    }
    @Override
   // @Scheduled(cron="${pos.time.check}")
    public void checkData() {
        try {
            FileInputStream fis = new FileInputStream(dataFileUrl);
            ObjectInputStream ois = new ObjectInputStream(fis);
            List<MonneyInfoLog> monneyInfoLogs= ( List<MonneyInfoLog>) ois.readObject();
            monneyInfoLogDao.save(monneyInfoLogs);
            //保存成功删除异常的数据
            monneyInfoLogList=new ArrayList<MonneyInfoLog>();
        }catch (Exception e){e.printStackTrace();}

    }

    @Override
    @Scheduled(cron="${pos.time.read}")
    public void readSetInfo() {

    }

    @Override
    public boolean control(MonneyInfoLog monneyInfoLog) {
       try {
           String id = monneyInfoLog.getTraceNo()+monneyInfoLog.getRefer(); //,验证人员唯一性的字段作;
            SfdevicebindEntity sfdevicebindEntity =sfdevicebindService.findByClientIp(getHostIp());
           //交易成功是否开闸
            if("Y".equals(sfdevicebindEntity.getConsumeSuccess())){
                opendDoor(id,monneyInfoLog, sfdevicebindEntity);
            }
           //4.是否登记人脸设置
           if( "Y".equals(sfdevicebindEntity.getSetFace()) ){
               Person p = new Person();
               p.setId(id);//ID,验证人员唯一性的字段作
               p.setName(faceName);//人员的名字
               p.setIC_NO(monneyInfoLog.getRefer());//为维根号发送到闸机
               p.setID_NO(monneyInfoLog.getCardNo());//	员工身份证号
               for (int i=0; i<repeatCount; i++){
                   boolean photographResult = faceService.photograph(p);
                   //如果没有拍照没有成功，则进行再次拍照
                   if(photographResult){
                       break;
                   }
               }
           }

           //5.登记人脸是否开闸设置
           if( "Y".equals(sfdevicebindEntity.getFaceSwingcard() )  ){
               opendDoor( id,monneyInfoLog, sfdevicebindEntity);
           }


        }catch (Exception e) {
         e.printStackTrace();
        }
        return false;
    }

    public void opendDoor(String id,MonneyInfoLog monneyInfoLog,SfdevicebindEntity sfdevicebindEntity) {

        String code = "0";
        //6.开闸方式选择设置
        if( "1".equals(sfdevicebindEntity.getSwingcardMode() ) ){
            //
            logger.info("【游娃娃别开闸】");
            try {
                JSONObject json = new JSONObject();
                json.put("Vol", vol);
                json.put("Screemconten", screemconten);
                json.put("Card_no", monneyInfoLog.getCardNo());
                json.put("Amount", monneyInfoLog.getAmount());
                json.put("Bank_code", monneyInfoLog.getBankCode());
                json.put("Expr", monneyInfoLog.getExprDate());
                json.put("Trace", monneyInfoLog.getTraceNo());
                json.put("Refer", monneyInfoLog.getRefer());
                json.put("Auth", monneyInfoLog.getAuthNo());
                json.put("Batch", monneyInfoLog.getBatchNo());
                json.put("Date", monneyInfoLog.getPayDate());
                json.put("Userno", monneyInfoLog.getUserno());
                json.put("Terno", monneyInfoLog.getTerno());
                json.put("Old_terno", monneyInfoLog.getOldTerno());
                json.put("OrderNo", monneyInfoLog.getOldTerno());
                json.put("Lrc", monneyInfoLog.getLrc());
                String result = null;
                result = FaceHttpClientUtil.doPostForString("http://"+sfdevicebindEntity.getSwingCardIp()+":"+sfdevicebindEntity.getSwingCardPort()+"/SwingCardService/OpenGate", json);
                JSONObject jsonObject1=JSONObject.fromObject(result);
                code=jsonObject1.getString("code");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            //todo 人脸识别开闸
            logger.info("【人脸识别开闸】");
            code = faceService.open();

        }

        if("200".equals(code)){
            SfGatelogEntity sfGatelogEntity=new SfGatelogEntity();
            sfGatelogEntity.setName(sfdevicebindEntity.getName());
            sfGatelogEntity.setIcNo(monneyInfoLog.getCardNo());
            sfGatelogEntity.setId(UUID.randomUUID().toString());
            sfGatelogEntity.setVisitor(sfdevicebindEntity.getUpdateName());
            sfGatelogEntity.setGateNo(sfdevicebindEntity.getClientIp());
            sfGatelogEntityDao.save(sfGatelogEntity);

        }else {
            logger.info("开闸失败了");
            // return false;
        }

    }



    @Override
    public boolean isWork() {
        //时间格式7-11;13-18
        SfdevicebindEntity sfdevicebindEntity =sfdevicebindService.findByClientIp(getHostIp());
        String dates[]=sfdevicebindEntity.getConsumeDate().split(";");
        int fristStartTime;
        int fristEndTime;
        int secondStartTime;
        int secondEndTime;
        String[] fristTimes=dates[0].split("-");
        String[] endTimes=dates[1].split("-");
        fristStartTime=Integer.parseInt(fristTimes[0]);
        fristEndTime=Integer.parseInt(fristTimes[1]);
        secondStartTime=Integer.parseInt(endTimes[0]);
        secondEndTime=Integer.parseInt(endTimes[1]);
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(new Date());
        int hour=calendar.get(Calendar.HOUR_OF_DAY);
        if((hour>=fristStartTime&&hour<fristEndTime) || (hour>=secondStartTime&&hour<secondEndTime) ){
            return true;
        }
        return false;
    }

    @Override
    public String getHostIp() {
            InetAddress addr = null;
            String clientIp = "";
            try {
                addr = InetAddress.getLocalHost();
                clientIp = addr.getHostAddress().toString(); //获取本机ip
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            return clientIp;
    }
    public static void main(String args[]){
        try {

        JSONObject json = new JSONObject();
        json.put("Vol", "222");
        json.put("Screemconten", "2222");
        json.put("Card_no", "22");
        json.put("Amount", "1");
        String result = null;
        result = FaceHttpClientUtil.doGetForString1("http://" + "127.0.0.1:8001" + "/SwingCardService/OpenGate", json);
        JSONObject jsonObject1=JSONObject.fromObject(result);
        String code=jsonObject1.getString("code");
            System.out.println(code+":2222222222222");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
